package com.mtoolkit.property.support;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.AbstractMap.SimpleEntry;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map.Entry;
import java.util.NoSuchElementException;
import java.util.Properties;
import java.util.Set;

import com.mtoolkit.util.EmptyUtil;

/**
 * 一个普通的属性文件操作的实现。
 * 内部保存一个java.util.Properties的实例，所有的方法将委托给java.util.Properties来实现。
 * @version 1.00 2010-10-8, 18:10:44
 * @since JDK 1.5
 * @author ZhangShixi
 */
public class CommonProperties extends AbstractProperties {

    //---- constractors --------------------------------------------------------
    /**
     * 无参构造器，尚未载入属性文件。
     */
    public CommonProperties() {
    }

    /**
     * 以给定的属性文件，构造一个普通的属性文件读取操作实例。
     * @param prop 要读取的属性文件。
     */
    public CommonProperties(Properties prop) {
        _prop = prop;
    }

    //---- public methods ------------------------------------------------------
    /**
     * 获取指定键对应的属性值。
     * @param key 键值对的键。
     * @return 键值对的键所对应的值。
     * @throws java.util.NoSuchElementException 如果指定的键不存在，将抛出此异常。
     */
    @Override
    public String getValue(String key) {
        String value = _prop.getProperty(key);
        if (EmptyUtil.isNotNullEmpty(value)) {
            return value;
        } else {
            throw new NoSuchElementException(
                    "Not found [" + "key" + "] element from properties.");
        }
    }

    /**
     * 获取属性文件中所有键的Set视图。
     * @return 键的Set视图。
     */
    @Override
    public Set<String> keySet() {
        Set<Object> keySet = _prop.keySet();
        if (keySet == null || keySet.isEmpty()) {
            return Collections.emptySet();
        }

        Set<String> returnKeySet = new HashSet<String>();
        for (Object key : keySet) {
            returnKeySet.add((String) key);
        }

        return returnKeySet;
    }

    /**
     * 获取属性文件中配置的所有的值列表。
     * @return 所有的值列表。
     * @ 获取属性异常。
     */
    @Override
    public List<String> valueList() {
        Collection<Object> values = _prop.values();
        if (values == null || values.isEmpty()) {
            return Collections.emptyList();
        }

        List<String> returnValues = new ArrayList<String>(values.size());
        for (Object value : values) {
            returnValues.add((String) value);
        }

        return returnValues;
    }

    /**
     * 获取属性文件中所有键值对的Set视图。
     * @return 所有键值对的Set视图。
     */
    @Override
    public Set<Entry<String, String>> entrySet() {
        Set<Entry<Object, Object>> entrySet = _prop.entrySet();
        if (entrySet == null || entrySet.isEmpty()) {
            return Collections.emptySet();
        }

        Set<Entry<String, String>> returnEntrySet = new HashSet<Entry<String, String>>();
        for (Entry<Object, Object> entry : entrySet) {
            returnEntrySet.add(
                    new SimpleEntry<String, String>(
                    (String) entry.getKey(), (String) entry.getValue()));
        }

        return returnEntrySet;
    }

    /**
     * 判断此属性文件配置中是否包含指定的键。
     * @param key 指定的键。
     * @return 是否包含指定的键。
     *      <code>true</code>包含，<code>false</code>不包含。
     */
    @Override
    public boolean containsKey(String key) {
        return _prop.containsKey(key);
    }

    /**
     * 判断此属性文件配置中是否包含指定的值。
     * @param value 指定的值。
     * @return 是否包含指定的值。
     *      <code>true</code>包含，<code>false</code>不包含。
     */
    @Override
    public boolean containsValue(String value) {
        return _prop.containsValue(value);
    }

    /**
     * 返回此属性文件中键值对的数量。
     * @return 属性文件中键值对的数量。
     */
    @Override
    public int size() {
        return _prop.size();
    }

    /**
     * 返回此属性文件是否为空。
     * @return 属性文件是否为空。
     *      <code>true</code>表示为空，<code>false</code>表示不为空。
     */
    @Override
    public boolean isEmpty() {
        return _prop.isEmpty();
    }

    //---- protected methods ---------------------------------------------------
    /**
     * 加载属性文件。
     * @param filePath 属性文件的路径。
     * @throws java.io.IOException 加载属性文件异常。
     */
    @Override
    protected void doLoadProperties(String filePath) throws IOException {
        InputStream input = new FileInputStream(filePath);
        Properties prop = new Properties();
        try {
            prop.load(input);
        } finally {
            input.close();
        }
        _prop = prop;
    }
    //---- privte attributs ----------------------------------------------------
    private Properties _prop; //内部保存树形文件信息的Properties容器。
}
